﻿#region Copyright & licence

// This file is part of Refix.
// 
// Refix is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
// 
// Refix is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with Refix.  If not, see <http://www.gnu.org/licenses/>.
// 
// Copyright (C) 2010-11 David Musgrove and others.

#endregion

using System;
using System.IO;
using System.Net;
using System.Text;

using Refix.Core.Properties;

namespace Refix.Core.Repository
{
    public class RemoteRepository
    {
        private string RepositoryUrl { get; set; }
        private string BaseDirectory { get; set; }

        public string Url
        {
            get { return RepositoryUrl ?? "http://repo.refixcentral.com"; }
        }

        public RemoteRepository() : this(Configuration.RemoteRepository, Directory.GetCurrentDirectory()) {}

        public RemoteRepository(string repositoryUrl, string baseDirectory)
        {
            RepositoryUrl = repositoryUrl;
            BaseDirectory = baseDirectory;
        }

        public virtual bool DownloadAllVersions(string assemblyName, string successMessage)
        {
            string requestUrl = Url + "/Get.aspx/" + assemblyName;
            return Download(assemblyName, requestUrl, successMessage);
        }

        public virtual bool DownloadVersion(string assemblyName, string version, string successMessage)
        {
            OutputWriter.WriteLine(OutputVerbosity.Verbose,
                                   string.Format("Downloading from: {0}/Get.aspx/{1}/{2}", Url, assemblyName, version));
            string requestUrl = string.Format("{0}/Get.aspx/{1}/{2}", Url, assemblyName, version);
            return Download(assemblyName, requestUrl, successMessage);
        }

        public virtual int GetComponentRevision(string assemblyName)
        {
            OutputWriter.WriteLine(OutputVerbosity.Verbose,
                       string.Format("Getting revision from: {0}/GetRevision.aspx/{1}", Url, assemblyName));
            string requestUrl = string.Format("{0}/GetRevision.aspx/{1}", Url, assemblyName);
            var request = (HttpWebRequest)WebRequest.Create(requestUrl);
            try
            {
                using (WebResponse response = request.GetResponse())
                {
                    var buffer = new byte[100];
                    int bytes = response.GetResponseStream().Read(buffer, 0, 100);
                    string responseString = Encoding.ASCII.GetString(buffer, 0, bytes);
                    int revision = int.Parse(responseString);
                    return revision;
                }
            }
            catch (WebException)
            {
                OutputWriter.WriteLine(OutputVerbosity.Quiet, ResourceDispenser.GetString("WEB_SERVER_NOT_REACHABLE"),
                                       requestUrl);
            }

            return -1;
        }


        private bool Download(string assemblyName, string requestUrl, string successMessage)
        {
            var request = (HttpWebRequest)WebRequest.Create(requestUrl);
            try
            {
                using (WebResponse response = request.GetResponse())
                {
                    if (response.ContentType == "application/zip")
                    {
                        string targetDirectory = PathUtilities.GetComponentPath(BaseDirectory, assemblyName);
                        string zipFileName = Path.Combine(targetDirectory, "remote.zip");
                        Directory.CreateDirectory(targetDirectory);
                        using (Stream input = response.GetResponseStream())
                        {
                            using (FileStream zipFile = File.Open(zipFileName, FileMode.Create))
                            {
                                int byteRead;
                                while ((byteRead = input.ReadByte()) >= 0)
                                {
                                    zipFile.WriteByte((byte)byteRead);
                                }
                            }
                        }
                        RepositoryUtilities.MergeZipFile(BaseDirectory, targetDirectory, zipFileName, MergeDirection.Download);
                        OutputWriter.WriteLine(OutputVerbosity.Normal, successMessage);
                    }
                    response.Close();
                }
                return true;
            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError)
                {
                    using (OutputWriter.Highlight(ConsoleColor.Yellow))
                    {
                        OutputWriter.WriteLine(OutputVerbosity.Quiet,
                                               ResourceDispenser.GetString("DOWNLOAD_NOT_FOUND"),
                                               requestUrl);
                    }
                }
                else
                {
                    using (OutputWriter.Highlight(ConsoleColor.Red))
                    {
                        OutputWriter.WriteLine(OutputVerbosity.Quiet,
                                               ResourceDispenser.GetString("WEB_SERVER_NOT_REACHABLE"),
                                               requestUrl);
                    }
                }
            }

            return false;
        }
    }
}